﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Common.Models;

namespace Common
{
    public class ReadInput
    {
        /// <summary>
        /// 根据文件路径打开文本返回文本内容
        /// </summary>
        /// <returns></returns>
        public static string GetStr(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath)) return "";
            var sr = new StreamReader(filePath, Encoding.UTF8);
            var str = sr.ReadToEnd();
            sr.Close();
            return str;
        }

        /// <summary>
        /// 读取文本中的画图数据
        /// </summary>
        /// <param name="str">文本字符流</param>
        /// <param name="outputs"></param>
        public static void ReadDraw(string str, ref List<Output> outputs)
        {
            //换行符用斜杠代替,方便读取
            //str = str.Replace("\r\n", "/");
            //以#分出每组排样结果
            var datas = str.Trim('\r', '\n').Split('#');

            //循环读取每组排样结果
            foreach (var t in datas)
            {
                if (string.IsNullOrWhiteSpace(t)) continue;
                //输出模型初始化
                var output = new Output();
                //以!分出一组排样结果的每种排样方式
                string[] data = t.Split('!');
                var dataNum = data.Length;
                //初步判断文本大体格式是否正确
                if (dataNum < 3)
                {
                    MessageBox.Show("导入的文本可能不完整！");
                    return;
                }
                //正则匹配计算规格数据
                var match = Regex.Match(data[0], @"^Length:\s*(\d+)\s*Width:\s*(\d+)\s*DiaTotalNum:(\d+)\s*Diameter:\s*(\s+\d+)*\s*Demand:\s*(\d+\s*)*\s*DiaNum:\s*(\d+\s*)*$", RegexOptions.IgnoreCase);
                if (!match.Success)
                {
                    MessageBox.Show("画图数据文本格式不对：\r\n" + t);
                    continue;
                }
                var groups = match.Groups;
                output.Length = double.Parse(groups[1].Value);
                output.Width = double.Parse(groups[2].Value);
                output.Num = int.Parse(groups[3].Value);
                if (groups[4].Captures.Count != output.Num)
                {
                    MessageBox.Show("画图数据文本格式不对：\r\n" + t);
                    continue;
                }
                output.Diameter = groups[4].Captures.Cast<Capture>().Select(o => double.Parse(o.Value.Trim())).ToArray();
                output.Demand = groups[5].Captures.Cast<Capture>().Select(o => int.Parse(o.Value.Trim())).ToArray();
                output.DiaNum = new List<int[]>();
                var diaNums = groups[6].Captures.Cast<Capture>().Select(o => int.Parse(o.Value.Trim())).ToArray();
                for (int i = 0; i < diaNums.Length; i++)
                {
                    var diaNumList = new List<int>();
                    do
                    {
                        diaNumList.Add(diaNums[i++]);
                    } while (i % output.Num != 0);
                    i--;
                    output.DiaNum.Add(diaNumList.ToArray());
                }

                output.Plates = new List<List<List<int[]>>>();

                #region!标志分隔的每种排样方式

                for (int j = 1; j < dataNum - 1; j++)
                {
                    data[j] = data[j].Replace("\r\n", "/");

                    //一种排样方式
                    output.Plate = new List<List<int[]>>();
                    //一个排样方式的所有数据
                    string[] plate = data[j].Split('/');
                    //所有椭圆的数据
                    output.Ellipses = new List<int[]>();
                    //所有直线的数据
                    output.Lines = new List<int[]>();
                    //所有矩形的数据
                    output.Rectangles = new List<int[]>();
                    //一个方式中的一条排
                    for (int k = 1; k < plate.Length - 1; k++)
                    {
                        string[] shapes = plate[k].Split(' ');
                        //将字符串数组转成整数数组
                        var shape = Array.ConvertAll(shapes, o => (int)double.Parse(o));
                        switch (shapes[0])
                        {
                            case "1":
                                output.Rectangles.Add(shape);
                                break;
                            case "2":
                                output.Ellipses.Add(shape);
                                break;
                            case "3":
                                output.Lines.Add(shape);
                                break;
                        }
                    }
                    output.Plate.Add(output.Ellipses);
                    output.Plate.Add(output.Lines);
                    output.Plate.Add(output.Rectangles);
                    output.Plates.Add(output.Plate);

                }

                #endregion
                //计算结果
                match = Regex.Match(data[dataNum - 1], @"TotalPlateNum:\s*(\d+)\s*UtilizationRate:\s*(0\.\d+)\s*", RegexOptions.IgnoreCase);
                if (!match.Success)
                {
                    MessageBox.Show("画图数据文本格式不对：\r\n" + t);
                    continue;
                }
                output.TotalPlateNum = int.Parse(match.Groups[1].Value);
                output.UtilizationRate = double.Parse(match.Groups[2].Value);
                //将每种排样结果添加到所有画图数据的全局静态变量中
                outputs.Add(output);
            }
        }

        /// <summary>
        /// 读取文本中的所有计算数据，转化为input列表
        /// </summary>
        /// <param name="str"></param>
        /// <param name="inputs"></param>
        public static void ReadCalc(string str, ref List<Input> inputs)
        {
            str = str.Trim('\r', '\n', '#');
            var inputStrs = str.Split('#');
            foreach (var item in inputStrs)
            {
                if (item != null)
                {
                    var input =new Input();
                    ReadData(item, out input);
                    inputs.Add(input);
                }
            }
        }

        /// <summary>
        /// 将一个输入字符串转换为input类
        /// </summary>
        public static void ReadData(string dataString, out Input input)
        {
            input = new Input();
            try
            {
                dataString = dataString.Trim('\r', '\n');
                var a = dataString.Trim('[', ']');
                var b = a.Replace("]\r\n[", "/");
                var c = b.Split('/');
                var i = 0;
                //板材长宽及毛胚种类数
                while (i < c.Length)
                {
                    var d = c[i++].Split(',');

                    if (d.Length != 3)
                    {
                        MessageBox.Show("数据格式错误！");
                        return;
                    }

                    input.Length = double.Parse(d[0]);
                    input.Width = double.Parse(d[1]);
                    input.Num = int.Parse(d[2]);
                    input.Diameter = new double[input.Num];
                    input.Demand = new int[input.Num];
                    input.Value = new double[input.Num];
                    input.Squer = 0.0;
                    for (int j = 0; j < input.Num; j++)
                    {
                        //毛胚规格及数量
                        var e = c[i++].Split(',');
                        input.Diameter[j] = double.Parse(e[0]);
                        input.Demand[j] = int.Parse(e[1]);
                        input.Value[j] = 1.0;
                        input.Squer += Math.PI * Math.Pow(input.Diameter[j] / 2, 2) * input.Demand[j];
                    }
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }

        public static void ToInput(out Input input)
        {
            input=new Input();
        }
    }
}
